// Copyright (c) 2023 Presto Labs Pte. Ltd.
// Author: tianqiang

#pragma once

#include <functional>
#include <string_view>
#include <unordered_set>

namespace coin2::exchange::base::order {

class SystemCriticalError {
 public:
  using Callback = std::function<void(const char*, int, std::string_view, std::string_view)>;

  SystemCriticalError(const SystemCriticalError&) = delete;
  void operator=(const SystemCriticalError&) = delete;

  void Log(const char* file, int line, std::string_view condition, std::string_view message);

  bool RegisterCallback(Callback* callback);

  bool UnregisterCallback(Callback* callback);

  static SystemCriticalError& Get();

 private:
  SystemCriticalError() = default;

  std::unordered_set<Callback*> callback_set_;
};

}  // namespace coin2::exchange::base::order

#define SYSTEM_CRITICAL_ERROR(condition, message)            \
  if (!(condition)) {                                        \
    coin2::exchange::base::order::SystemCriticalError::Get() \
        .Log(__FILE__, __LINE__, #condition, message);       \
  }
